user

您所在的位置:网站首页 GetUserInfo failed user

user

2023-04-21 14:04| 来源: 网络整理| 查看: 265

项目:user_system

下面是对于各个目录下的各个文件的函数的讲解。

1、config包(1)config.go

​ 这是一个 Go 语言的配置包,用于读取并解析配置文件。该包使用了 viper 库,可以读取 YAML 格式的配置文件。其中定义了一些结构体,分别对应了不同的配置项,例如日志配置、数据库配置、Redis 配置等等。使用者可以通过调用 GetGlobalConf() 函数获取全局配置文件,也可以通过调用 InitConfig() 函数来初始化日志。在 InitConfig() 函数中,会先获取全局配置文件,然后根据配置文件中的日志级别和输出方式等参数进行初始化,同时设置日志格式为 JSON 格式,并且打印文件位置和行号等信息。最后根据配置文件中的输出方式,将日志输出到终端或者文件中。

全局配置1234var ( config GlobalConfig // 全局业务配置文件 once sync.Once)

​ 配置全局业务配置文件,便于文件内的使用。

LogConf类型 日志配置

​ 日志输出的相关配置信息

1234567//LogConf 日志配置type LogConf struct { LogPattern string `yaml:"log_pattern" mapstructure:"log_pattern"` // 日志输出标准,终端输出/文件输出 LogPath string `yaml:"log_path" mapstructure:"log_path"` // 表示日志输出到文件时的路径。 SaveDays uint `yaml:"save_days" mapstructure:"save_days"` // 表示日志保存的天数,过期的日志文件将被删除。 Level string `yaml:"level" mapstructure:"level"` // 表示日志输出的级别,包括 DEBUG、INFO、WARN、ERROR、FATAL 等级别,级别从低到高依次增强。}

​ 结构体中的 yaml 和 mapstructure 标签是用于指定将结构体序列化和反序列化为YAML和Map类型时,如何将结构体字段映射到YAML或Map中的键名。

​ 具体来说,yaml:"log_pattern" 表示在序列化为YAML格式时,LogPattern 字段将被映射到键名为 log_pattern 的YAML键;mapstructure:"log_pattern" 则表示在反序列化时,YAML中的 log_pattern 键将被映射到 LogPattern 字段。

​ 类似的,yaml:"log_path" 和 mapstructure:"log_path" 表示 LogPath 字段的映射关系;yaml:"save_days" 和 mapstructure:"save_days" 表示 SaveDays 字段的映射关系;yaml:"level" 和 mapstructure:"level" 表示 Level 字段的映射关系。这些标签的使用使得在不同的格式中读取和写入配置变得更加方便。

DbConf类型 db配置结构

​ 数据库连接的相关配置信息

12345678910type DbConf struct { Host string `yaml:"host" mapstructure:"host"` // db主机地址 Port string `yaml:"port" mapstructure:"port"` // db端口 User string `yaml:"user" mapstructure:"user"` // 用户名 Password string `yaml:"password" mapstructure:"password"` // 密码 Dbname string `yaml:"dbname" mapstructure:"dbname"` // db名 MaxIdleConn int `yaml:"max_idle_conn" mapstructure:"max_idle_conn"` // 最大空闲连接数 MaxOpenConn int `yaml:"max_open_conn" mapstructure:"max_open_conn"` // 最大打开的连接数 MaxIdleTime int64 `yaml:"max_idle_time" mapstructure:"max_idle_time"` // 连接最大空闲时间}

结构体中的 yaml 和 mapstructure 标签作用如上所述,在后续中也不再赘述。

AppConf类型 服务配置

​ 描述应用程序的基本配置信息

123456type AppConf struct { AppName string `yaml:"app_name" mapstructure:"app_name"` // 业务名 Version string `yaml:"version" mapstructure:"version"` // 版本 Port int `yaml:"port" mapstructure:"port"` // 端口 RunMode string `yaml:"run_mode" mapstructure:"run_mode"` // 运行模式} RedisConf类型 配置

​ 描述 Redis 数据库的配置信息

1234567type RedisConf struct { Host string `yaml:"rhost" mapstructure:"rhost"` // db主机地址 Port int `yaml:"rport" mapstructure:"rport"` // db端口 DB int `yaml:"rdb" mapstructure:"rdb"` //表示 Redis 服务器上的哪个数据库,从0到15共16个数据库。 PassWord string `yaml:"passwd" mapstructure:"passwd"` //表示连接 Redis 服务器所需的密码,如果没有设置密码则该字段为空字符串。 PoolSize int `yaml:"poolsize" mapstructure:"poolsize"` //连接池的大小,即最大连接数。} Cache类型 缓存

​ 定义了缓存相关的配置信息

1234type Cache struct { SessionExpired int `yaml:"session_expired" mapstructure:"session_expired"` //表示会话过期时间 UserExpired int `yaml:"user_expired" mapstructure:"user_expired"` //表示用户信息过期时间} GlobalConfig函数 业务配置结构体

​ 根据嵌套自定义的结构体业务配置结构体

12345678type GlobalConfig struct { AppConfig AppConf `yaml:"app" mapstructure:"app"` CorsOrigin []string `yaml:"cors_origin" mapstructure:"cors_origin"` // 跨域源列表 DbConfig DbConf `yaml:"db" mapstructure:"db"` // db配置 LogConfig LogConf `yaml:"log" mapstructure:"log"` // 日志配置 RedisConfig RedisConf `yaml:"redis" mapstructure:"redis"` // redis配置 Cache Cache `yaml:"cache" mapstructure:"cache"` // cache配置} readConf函数 读取应用程序配置文件

​ 使用 viper 库读取 YAML 格式的配置文件,并将配置信息解析到 config 变量中。

12345678910111213141516func readConf() { viper.SetConfigName("app") viper.SetConfigType("yml") viper.AddConfigPath(".") viper.AddConfigPath("./conf") viper.AddConfigPath("../conf") err := viper.ReadInConfig() if err != nil { panic("read config file err:" + err.Error()) } err = viper.Unmarshal(&config) if err != nil { panic("config file unmarshal err:" + err.Error()) } log.Infof("config === %+v", config)}

​ 在函数内部,首先通过 viper.SetConfigName()、viper.SetConfigType() 和 viper.AddConfigPath() 函数指定了配置文件的名称、类型和路径,然后通过 viper.ReadInConfig() 函数读取配置文件。

​ 读取配置文件后,使用 viper.Unmarshal() 函数将配置信息解析到 config 变量中,解析过程中会按照结构体成员的标签信息来读取配置项的值。

​ 最后,在解析完成后,使用日志库打印出读取到的配置信息,并将 config 变量保存在全局变量中供后续使用。需要注意的是,为了保证全局变量只被初始化一次,这里使用了 sync.Once 来实现懒汉式单例模式。

GetGlobalConf函数 获取全局配置文件1234func GetGlobalConf() *GlobalConfig { once.Do(readConf) return &config}

​ 这段代码定义了一个函数 GetGlobalConf(),它返回一个指向 GlobalConfig 结构体的指针。该函数使用了 sync.Once 类型的变量 once,以确保 readConf() 函数只被调用一次来读取配置文件,并将解析的结果存储在 config 变量中。 readConf() 函数负责从配置文件中读取配置信息,并使用 viper 库解析 YAML 格式的配置文件。

InitConfig函数 初始化日志12345678910111213141516171819202122232425262728293031323334353637func InitConfig() { globalConf := GetGlobalConf() //获取全局配置文件 // 设置日志级别 level, err := log.ParseLevel(globalConf.LogConfig.Level) //实现字符串到log.Level类型的转换 if err != nil { panic("log level parse err:" + err.Error()) } // 设置日志格式为json格式 log.SetFormatter(&logFormatter{ log.TextFormatter{ DisableColors: true, TimestampFormat: "2006-01-02 15:04:05", FullTimestamp: true, }}) log.SetReportCaller(true) // 打印文件位置,行号 log.SetLevel(level) //设置日志的记录级别 switch globalConf.LogConfig.LogPattern { case "stdout": log.SetOutput(os.Stdout) case "stderr": log.SetOutput(os.Stderr) case "file": logger, err := rlog.New( globalConf.LogConfig.LogPath+".%Y%m%d", //rlog.WithLinkName(globalConf.LogConf.LogPath), rlog.WithRotationCount(globalConf.LogConfig.SaveDays), //rlog.WithMaxAge(time.Minute*3), rlog.WithRotationTime(time.Hour*24), ) if err != nil { panic("log conf err: " + err.Error()) } log.SetOutput(logger) default: panic("log conf err, check log_pattern in logsvr.yaml") }}

​ 首先,它调用GetGlobalConf()函数获取全局配置;接着,根据配置设置日志级别、格式和输出方式。

​ 全局配置文件中的日志级别是字符串类型,需要转换为logrus包中的log.Level类型,以便于后续日志记录和输出。这里使用了logrus包中的ParseLevel函数来实现字符串到log.Level类型的转换。如果解析失败,err不为nil,否则level变量存储解析得到的日志级别。

log.SetOutput:是一个函数,它设置logger输出的目的地。它需要一个io.Writer类型的参数,通常会传入os.Stdout(标准输出)或os.Stderr(标准错误输出)来控制日志信息的输出位置。

​ 最后,根据全局配置中的日志输出标准globalConf.LogConfig.LogPattern来设置日志输出位置,可以是标准输出stdout、标准错误输出stderr或文件输出file,文件输出需要指定文件路径和日志保留时间。如果日志输出标准不合法,则会抛出异常。

完整代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130package config

import ( rlog "github.com/lestrrat-go/file-rotatelogs" log "github.com/sirupsen/logrus" "os" "sync" "time"

"github.com/spf13/viper")

var ( config GlobalConfig // 全局业务配置文件 once sync.Once)

// LogConf 日志配置type LogConf struct { LogPattern string `yaml:"log_pattern" mapstructure:"log_pattern"` // 日志输出标准,终端输出/文件输出 LogPath string `yaml:"log_path" mapstructure:"log_path"` // 日志路径 SaveDays uint `yaml:"save_days" mapstructure:"save_days"` // 日志保存天数 Level string `yaml:"level" mapstructure:"level"` // 日志级别}

// DbConf db配置结构type DbConf struct { Host string `yaml:"host" mapstructure:"host"` // db主机地址 Port string `yaml:"port" mapstructure:"port"` // db端口 User string `yaml:"user" mapstructure:"user"` // 用户名 Password string `yaml:"password" mapstructure:"password"` // 密码 Dbname string `yaml:"dbname" mapstructure:"dbname"` // db名 MaxIdleConn int `yaml:"max_idle_conn" mapstructure:"max_idle_conn"` // 最大空闲连接数 MaxOpenConn int `yaml:"max_open_conn" mapstructure:"max_open_conn"` // 最大打开的连接数 MaxIdleTime int64 `yaml:"max_idle_time" mapstructure:"max_idle_time"` // 连接最大空闲时间}

// AppConf 服务配置type AppConf struct { AppName string `yaml:"app_name" mapstructure:"app_name"` // 业务名 Version string `yaml:"version" mapstructure:"version"` // 版本 Port int `yaml:"port" mapstructure:"port"` // 端口 RunMode string `yaml:"run_mode" mapstructure:"run_mode"` // 运行模式}

// RedisConf 配置type RedisConf struct { Host string `yaml:"rhost" mapstructure:"rhost"` // db主机地址 Port int `yaml:"rport" mapstructure:"rport"` // db端口 DB int `yaml:"rdb" mapstructure:"rdb"` //表示 Redis 服务器上的哪个数据库,从0到15共16个数据库。 PassWord string `yaml:"passwd" mapstructure:"passwd"` //表示连接 Redis 服务器所需的密码,如果没有设置密码则该字段为空字符串。 PoolSize int `yaml:"poolsize" mapstructure:"poolsize"` //连接池的大小,即最大连接数。}

type Cache struct { SessionExpired int `yaml:"session_expired" mapstructure:"session_expired"` //表示会话过期时间 UserExpired int `yaml:"user_expired" mapstructure:"user_expired"` //表示用户信息过期时间}

// GlobalConfig 业务配置结构体type GlobalConfig struct { AppConfig AppConf `yaml:"app" mapstructure:"app"` CorsOrigin []string `yaml:"cors_origin" mapstructure:"cors_origin"` // 跨域源列表 DbConfig DbConf `yaml:"db" mapstructure:"db"` // db配置 LogConfig LogConf `yaml:"log" mapstructure:"log"` // 日志配置 RedisConfig RedisConf `yaml:"redis" mapstructure:"redis"` // redis配置 Cache Cache `yaml:"cache" mapstructure:"cache"` // cache配置}

// GetGlobalConf 获取全局配置文件func GetGlobalConf() *GlobalConfig { once.Do(readConf) return &config}

func readConf() { viper.SetConfigName("app") viper.SetConfigType("yml") viper.AddConfigPath(".") viper.AddConfigPath("./conf") viper.AddConfigPath("../conf") err := viper.ReadInConfig() if err != nil { panic("read config file err:" + err.Error()) } err = viper.Unmarshal(&config) if err != nil { panic("config file unmarshal err:" + err.Error()) } log.Infof("config === %+v", config)}

// InitConfig 初始化日志func InitConfig() { globalConf := GetGlobalConf() //获取全局配置文件 // 设置日志级别 level, err := log.ParseLevel(globalConf.LogConfig.Level) //实现字符串到log.Level类型的转换 if err != nil { panic("log level parse err:" + err.Error()) } // 设置日志格式为json格式 log.SetFormatter(&logFormatter{ log.TextFormatter{ DisableColors: true, TimestampFormat: "2006-01-02 15:04:05", FullTimestamp: true, }}) log.SetReportCaller(true) // 打印文件位置,行号 log.SetLevel(level) //设置日志的记录级别 switch globalConf.LogConfig.LogPattern { case "stdout": log.SetOutput(os.Stdout) case "stderr": log.SetOutput(os.Stderr) case "file": logger, err := rlog.New( globalConf.LogConfig.LogPath+".%Y%m%d", //rlog.WithLinkName(globalConf.LogConf.LogPath), rlog.WithRotationCount(globalConf.LogConfig.SaveDays), //rlog.WithMaxAge(time.Minute*3), rlog.WithRotationTime(time.Hour*24), ) if err != nil { panic("log conf err: " + err.Error()) } log.SetOutput(logger) default: panic("log conf err, check log_pattern in logsvr.yaml") }}

(2)log.go

​ 这是一个 Go 语言包(package)的实现,其中包含了以下函数和结构体:

logFormatter:自定义的日志格式化结构体,包含 Format 方法,用于格式化日志输出。 setGinLog:设置 Gin 框架的日志输出目标的函数,将日志输出到指定的 io.Writer 对象中。

具体来说,logFormatter 结构体重写了 TextFormatter 的 Format 方法,通过调用 prettyCaller 函数来输出日志所在的文件和行号信息,同时输出日志时间、日志等级和日志内容,并返回格式化后的字节数组。

在 setGinLog 函数中,通过将 out 参数赋值给 gin.DefaultWriter 和 gin.DefaultErrorWriter,将 Gin 框架的日志输出目标设置为指定的 io.Writer 对象,以此来实现日志的输出。

logFormatter 类型

​ tabFormatter tab数据格式化

123type logFormatter struct { log.TextFormatter}

​ 定义了一个新的类型 logFormatter,它是 log.TextFormatter 的子类型。

​ 换句话说,logFormatter 继承了 log.TextFormatter 中定义的所有属性和方法,并且可以在此基础上添加额外的属性和方法。

​ 这种方式称为组合,即将一个或多个类型组合成一个新类型。在这个例子中,logFormatter 可以用来定制化 logrus 日志库中的日志格式。

Format 函数

​ 自定义日志输出格式

12345678910111213141516171819func (c *logFormatter) Format(entry *log.Entry) ([]byte, error) { prettyCaller := func(frame *runtime.Frame) string { _, fileName := filepath.Split(frame.File) return fmt.Sprintf("%s:%d", fileName, frame.Line) } var b *bytes.Buffer if entry.Buffer != nil { b = entry.Buffer } else { b = &bytes.Buffer{} } b.WriteString(fmt.Sprintf("[%s] %s", entry.Time.Format(c.TimestampFormat), // 输出日志时间 strings.ToUpper(entry.Level.String()))) if entry.HasCaller() { b.WriteString(fmt.Sprintf("[%s]", prettyCaller(entry.Caller))) // 输出日志所在文件,行数位置 } b.WriteString(fmt.Sprintf(" %s\n", entry.Message)) // 输出日志内容 return b.Bytes(), nil}

​ 定义了一个实现了 log.Formatter 接口的 logFormatter 结构体,并实现了 Format 方法,用于格式化日志输出。具体来说,Format 方法会接收一个 log.Entry 结构体指针作为参数,该结构体包含了日志的时间、级别、消息内容等信息,并返回一个字节数组和一个错误对象。

​ 在 Format 方法中,首先定义了一个 prettyCaller 函数,用于获取日志输出所在文件和行数。然后,根据传入的 log.Entry 指针中的信息,将时间、级别、所在位置、消息内容等信息依次输出到一个 bytes.Buffer 对象中,并最终返回该对象的字节数组表示。

​ 此外,还定义了一个名为 setGinLog 的函数,用于设置 gin 框架的日志输出到指定的 io.Writer 对象,通常用于将 gin 的日志输出到文件中。

setGinLog 函数

​ 修改 gin 框架的日志输出位置

1234func setGinLog(out io.Writer) { gin.DefaultWriter = out gin.DefaultErrorWriter = out}

​ 接收一个实现了 io.Writer 接口的对象作为参数 out。在函数内部,将 gin 框架的默认日志输出和错误输出都设置为 out。也就是说,通过调用这个函数可以修改 gin 框架的日志输出位置。

完整代码12345678910111213141516171819202122232425262728293031323334353637383940414243package config

import ( "bytes" "fmt" "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" "io" "path/filepath" "runtime" "strings")

//tabFormatter tab数据格式化type logFormatter struct { log.TextFormatter}

// Format 自定义日志输出格式func (c *logFormatter) Format(entry *log.Entry) ([]byte, error) { prettyCaller := func(frame *runtime.Frame) string { _, fileName := filepath.Split(frame.File) return fmt.Sprintf("%s:%d", fileName, frame.Line) } var b *bytes.Buffer if entry.Buffer != nil { b = entry.Buffer } else { b = &bytes.Buffer{} } b.WriteString(fmt.Sprintf("[%s] %s", entry.Time.Format(c.TimestampFormat), // 输出日志时间 strings.ToUpper(entry.Level.String()))) if entry.HasCaller() { b.WriteString(fmt.Sprintf("[%s]", prettyCaller(entry.Caller))) // 输出日志所在文件,行数位置 } b.WriteString(fmt.Sprintf(" %s\n", entry.Message)) // 输出日志内容 return b.Bytes(), nil}

func setGinLog(out io.Writer) { gin.DefaultWriter = out gin.DefaultErrorWriter = out}

2、internal包(1)router包① router.gosetAppRunMode 设置运行模式12345func setAppRunMode() { if config.GetGlobalConf().AppConfig.RunMode == "release" { gin.SetMode(gin.ReleaseMode) }}

​ 用于设置应用程序运行模式。如果全局配置中的 AppConfig.RunMode 设置为 "release",那么会将 Gin 框架的模式设置为 Release 模式。

​ 在 Release 模式下,Gin 框架会禁用一些调试信息和中间件,以提高应用程序的运行效率和安全性。这是一个常见的最佳实践,特别是在生产环境中。

AuthMiddleWare函数

​ 验证用户身份是否合法

1234567891011121314func AuthMiddleWare() gin.HandlerFunc { return func(c *gin.Context) { if session, err := c.Cookie(constant.SessionKey); err == nil { if session != "" { c.Next() return } } // 返回错误 c.JSON(http.StatusUnauthorized, gin.H{"error": "err"}) c.Abort() return }}

​ 中间件函数接收一个 Gin 上下文对象(gin.Context),并返回一个 gin.HandlerFunc 类型的函数。中间件函数首先检查请求头中是否包含名为 constant.SessionKey 的 cookie。

​ 如果 cookie 存在且不为空,则说明用户已经登录,调用 c.Next() 方法,继续处理该请求并传递给后续处理程序;否则,中间件函数返回一个状态码为 http.StatusUnauthorized 的 JSON 响应,提示用户未授权,并终止该请求的处理,调用 c.Abort() 方法终止后续处理程序函数的执行。

InitRouterAndServe

​ 函数路由配置、启动服务

12345678910111213141516171819202122232425262728func InitRouterAndServe() {

setAppRunMode() r := gin.Default()

// 健康检查 r.GET("ping", api.Ping) //健康检查 // 用户注册 r.POST("/user/register", api.Register) // 用户登录 r.POST("/user/login", api.Login) // 用户登出 r.POST("/user/logout", AuthMiddleWare(), api.Logout) // 获取用户信息 r.GET("/user/get_user_info", AuthMiddleWare(), api.GetUserInfo) // 更新用户信息 r.POST("/user/update_nick_name", AuthMiddleWare(), api.UpdateNickName)

r.Static("/static/", "./web/static/") r.Static("/upload/images/", "./web/upload/images/")

// 启动server port := config.GetGlobalConf().AppConfig.Port if err := r.Run(":" + strconv.Itoa(port)); err != nil { log.Error("start server err:" + err.Error()) }}

​ 这个函数主要是初始化路由并启动HTTP server。

​ 首先调用setAppRunMode()函数来设置Gin框架的运行模式。然后创建一个默认的Gin实例,并使用GET方法注册了一个名为”ping”的路由,并将其处理函数设置为api.Ping,该函数用于实现健康检查。

​ 接下来注册了一系列处理用户相关操作的路由,如注册、登录、登出、获取用户信息以及更新用户昵称等。其中,访问需要用户授权的路由时,使用了AuthMiddleWare()中间件函数来验证用户的登录状态。

​ 最后,使用r.Static()函数注册了静态文件服务,指定了静态文件的路径。最后启动HTTP server,并指定了端口号。如果启动失败,将会输出错误信息到日志中。

完整代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263package router

import ( "github.com/gin-gonic/gin" log "github.com/sirupsen/logrus" "net/http" "strconv" api "user_system/api/http/v1" "user_system/config" "user_system/pkg/constant")

// InitRouterAndServe 路由配置、启动服务func InitRouterAndServe() {

setAppRunMode() r := gin.Default()

// 健康检查 r.GET("ping", api.Ping) //健康检查 // 用户注册 r.POST("/user/register", api.Register) // 用户登录 r.POST("/user/login", api.Login) // 用户登出 r.POST("/user/logout", AuthMiddleWare(), api.Logout) // 获取用户信息 r.GET("/user/get_user_info", AuthMiddleWare(), api.GetUserInfo) // 更新用户信息 r.POST("/user/update_nick_name", AuthMiddleWare(), api.UpdateNickName)

r.Static("/static/", "./web/static/") r.Static("/upload/images/", "./web/upload/images/")

// 启动server port := config.GetGlobalConf().AppConfig.Port if err := r.Run(":" + strconv.Itoa(port)); err != nil { log.Error("start server err:" + err.Error()) }}

// setAppRunMode 设置运行模式func setAppRunMode() { if config.GetGlobalConf().AppConfig.RunMode == "release" { gin.SetMode(gin.ReleaseMode) }}

func AuthMiddleWare() gin.HandlerFunc { return func(c *gin.Context) { if session, err := c.Cookie(constant.SessionKey); err == nil { if session != "" { c.Next() return } } // 返回错误 c.JSON(http.StatusUnauthorized, gin.H{"error": "err"}) c.Abort() return }}

(2)model包① model.goCreateModel类型 内嵌model1234type CreateModel struct { Creator string `gorm:"type:varchar(100);not null;default ''"` CreateTime time.Time `gorm:"autoCreateTime"` // 在创建记录时自动生成时间}

​ 这个是一个 Golang 结构体定义,用于定义一个数据表模型。其中 CreateModel 表示一个模型,它包含了两个字段:

​ a.Creator:表示模型的创建者,类型为字符串,占用数据库中的 varchar(100) 类型,不允许为空,如果不填则默认为空字符串。

​ b.CreateTime:表示模型的创建时间,类型为 time.Time,它是在创建记录时自动生成的时间。

这个模型是使用 GORM 框架来操作数据库的,通过在字段的 tag 中指定各种约束条件,例如 type、not null、default、autoCreateTime 等来指定该字段在数据库中的属性和行为。

ModifyModel类型 内嵌model1234type ModifyModel struct { Modifier string `gorm:"type:varchar(100);not null;default ''"` ModifyTime time.Time `gorm:"autoUpdateTime"` // 在更新记录时自动生成时间}

​ 这是一个包含Modifier和ModifyTime字段的结构体,用于对记录进行更新时自动记录修改者和修改时间。

​ Modifier字段是一个string类型,用于记录更新操作的人员,gorm:"type:varchar(100);not null;default ''"表示该字段在数据库中对应的类型为varchar(100),不能为空,并且默认值为''。

​ ModifyTime字段是一个time.Time类型,用于记录更新操作的时间,gorm:"autoUpdateTime"表示该字段在更新记录时会自动更新为当前时间。当记录被更新时,gorm会自动将当前时间赋值给ModifyTime字段。

​ 这种方式可以方便地记录记录的修改者和修改时间,且不需要手动在代码中添加修改者和修改时间的记录。同时,由于gorm自动更新时间的特性,确保了记录的修改时间的准确性。

User类型 用户12345678910type User struct { CreateModel ModifyModel ID int `gorm:"column:id"` Name string `gorm:"column:name"` //姓名 Gender string `gorm:"column:gender"` //性别 Age int `gorm:"column:age"` //年龄 PassWord string `gorm:"column:password"` //密码 NickName string `gorm:"column:nickname"` //昵称}

​ 定义了一个结构体 User,其中包含了 CreateModel 和 ModifyModel 两个嵌套的结构体。

​ CreateModel 结构体中包含了一个字段 CreateTime,它的类型为 time.Time,表示创建记录时自动生成的时间。

​ ModifyModel 结构体中包含了一个字段 ModifyTime,它的类型也为 time.Time,表示更新记录时自动生成的时间。

​ User 结构体中还包含了其他字段,如 ID、Name、Gender、Age、PassWord 和 NickName 等字段,这些字段可以通过在数据库中创建对应的列来存储数据。同时,由于 User 结构体嵌套了 CreateModel 和 ModifyModel 结构体,因此在插入或更新 User 记录时,相应的时间字段会自动填充为当前时间。

TableName 表名123func (t *User) TableName() string { return "t_user"}

​ 这是一个 GORM 模型结构体方法,用于指定模型对应的数据库表名。在这个例子中,User 模型对应的数据库表名为 t_user。这个方法的作用是将模型和表名进行绑定,使得 GORM 可以自动地将模型的数据存储到对应的数据库表中。如果没有显式指定表名,则 GORM 会默认使用模型名的复数形式作为表名。

完整代码1234567891011121314151617181920212223242526272829303132package model

import "time"

// CreateModel 内嵌modeltype CreateModel struct { Creator string `gorm:"type:varchar(100);not null;default ''"` CreateTime time.Time `gorm:"autoCreateTime"` // 在创建记录时自动生成时间}

// ModifyModel 内嵌modeltype ModifyModel struct { Modifier string `gorm:"type:varchar(100);not null;default ''"` ModifyTime time.Time `gorm:"autoUpdateTime"` // 在更新记录时自动生成时间}

// User 用户type User struct { CreateModel ModifyModel ID int `gorm:"column:id"` Name string `gorm:"column:name"` //姓名 Gender string `gorm:"column:gender"` //性别 Age int `gorm:"column:age"` //年龄 PassWord string `gorm:"column:password"` //密码 NickName string `gorm:"column:nickname"` //昵称}

// TableName 表名func (t *User) TableName() string { return "t_user"}

(3)dao包① user.goCreateUser函数 创建一个用户12345678func CreateUser(user *model.User) error { if err := utils.GetDB().Model(&model.User{}).Create(user).Error; err != nil { log.Errorf("CreateUser fail: %v", err) return fmt.Errorf("CreateUser fail: %v", err) } log.Infof("insert success") return nil}

​ 用于在数据库中创建一个新的用户记录。函数接受一个指向model.User类型结构体的指针作为参数,该结构体表示一个用户的数据。

​ 函数首先使用utils包中的GetDB函数获取一个数据库对象,并使用该对象的Model方法指定要操作的数据库表(model.User{}表示t_user表)。然后,它使用该表的Create方法来将传入的user结构体创建为一条新记录。如果创建过程中出现错误,函数会记录一个错误日志,并返回一个错误。否则,函数记录一个成功的信息日志并返回nil表示没有错误。

GetUserByName函数 根据姓名获取用户1234567891011func GetUserByName(name string) (*model.User, error) { user := &model.User{} if err := utils.GetDB().Model(model.User{}).Where("name=?", name).First(user).Error; err != nil { if err.Error() == gorm.ErrRecordNotFound.Error() { return nil, nil } log.Errorf("GetUserByName fail:%v", err) return nil, fmt.Errorf("GetUserByName fail:%v", err) } return user, nil}

​ 该函数用于从数据库中查找一个指定名称的用户,并返回一个指向该用户的指针。如果找不到该用户,则返回nil。

​ 它采用一个名称字符串作为输入参数,并使用该参数在数据库中查询匹配的用户记录。如果查询成功,它将返回指向用户记录的指针;否则,它将返回一个错误,该错误将描述查询失败的原因。

​ 在该函数内部,它使用了gorm库提供的方法来查询数据库,并将查询结果存储在一个指向User结构体的指针中。如果查询未能返回任何结果,即指定名称的用户不存在,则该函数将返回nil。否则,它将返回一个指向包含匹配用户信息的结构体的指针。

UpdateUserInfo 更新昵称123func UpdateUserInfo(userName string, user *model.User) int64 { return utils.GetDB().Model(&model.User{}).Where("`name` = ?", userName).Updates(user).RowsAffected}

​ 这个函数的功能是更新数据库中用户信息。它接收两个参数,一个是userName,代表要更新信息的用户的用户名;另一个是user指针,它是要更新的用户信息。

​ 在函数内部,使用utils.GetDB()方法获取数据库连接对象,然后使用Model方法指定操作的数据表。Where方法根据指定的用户名查询要更新的用户信息,并使用Updates方法将用户信息更新到数据库中。最后,RowsAffected方法返回更新的行数。

​ 这个函数的返回值是更新的行数,可以用于判断更新是否成功。

完整代码12345678910111213141516171819202122232425262728293031323334353637package dao

import ( "fmt" log "github.com/sirupsen/logrus" "gorm.io/gorm" "user_system/internal/model" "user_system/utils")

// GetUserByName 根据姓名获取用户func GetUserByName(name string) (*model.User, error) { user := &model.User{} if err := utils.GetDB().Model(model.User{}).Where("name=?", name).First(user).Error; err != nil { if err.Error() == gorm.ErrRecordNotFound.Error() { return nil, nil } log.Errorf("GetUserByName fail:%v", err) return nil, fmt.Errorf("GetUserByName fail:%v", err) } return user, nil}

// CreateUser 创建一个用户func CreateUser(user *model.User) error { if err := utils.GetDB().Model(&model.User{}).Create(user).Error; err != nil { log.Errorf("CreateUser fail: %v", err) return fmt.Errorf("CreateUser fail: %v", err) } log.Infof("insert success") return nil}

// UpdateUserInfo 更新昵称func UpdateUserInfo(userName string, user *model.User) int64 { return utils.GetDB().Model(&model.User{}).Where("`name` = ?", userName).Updates(user).RowsAffected}

(4)service包① entity.goRegisterRequest类型 注册请求1234567type RegisterRequest struct { UserName string `json:"user_name"` Password string `json:"pass_word"` Age int `json:"age"` Gender string `json:"gender"` NickName string `json:"nick_name"`}

RegisterRequest 是一个结构体,包含了注册请求的参数信息。其中包括:

UserName:字符串类型,表示用户名。 Password:字符串类型,表示用户密码。 Age:整型,表示用户年龄。 Gender:字符串类型,表示用户性别。 NickName:字符串类型,表示用户昵称。 LoginRequest类型 登陆请求1234type LoginRequest struct { UserName string `json:"user_name"` PassWord string `json:"pass_word"`}

LoginRequest 结构体,用于表示登录请求。它包含两个字段:

UserName:表示用户的名称的字符串类型。 PassWord:表示用户密码的字符串类型。 LogoutRequest类型 登出请求123type LogoutRequest struct { UserName string `json:"user_name"`}

UserName:表示要注销用户的用户名(string类型)。

GetUserInfoRequest 获取用户信息请求123type GetUserInfoRequest struct { UserName string `json:"user_name"`}

一个获取用户信息的请求结构体,它只有一个字段:

UserName:表示要获取信息的用户的用户名,类型为字符串。 GetUserInfoResponse 获取用户信息返回结构1234567type GetUserInfoResponse struct { UserName string `json:"user_name"` Age int `json:"age"` Gender string `json:"gender"` PassWord string `json:"pass_word"` NickName string `json:"nick_name"`}

GetUserInfoResponse 是获取用户信息的返回结构,包含以下字段:

UserName:用户名称。 Age:用户年龄。 Gender:用户性别。 PassWord:用户密码。 NickName:用户昵称。 UpdateNickNameRequest 修改用户信息返回结构1234type UpdateNickNameRequest struct { UserName string `json:"user_name"` NewNickName string `json:"new_nick_name"`}

表示修改用户昵称的请求。它有两个字段:

UserName:字符串类型,表示要修改昵称的用户的名称。 NewNickName:字符串类型,表示用户要修改的新昵称。 完整代码1234567891011121314151617181920212223242526272829303132333435363738394041package service

// RegisterRequest 注册请求type RegisterRequest struct { UserName string `json:"user_name"` Password string `json:"pass_word"` Age int `json:"age"` Gender string `json:"gender"` NickName string `json:"nick_name"`}

// LoginRequest 登陆请求type LoginRequest struct { UserName string `json:"user_name"` PassWord string `json:"pass_word"`}

// LogoutRequest 登出请求type LogoutRequest struct { UserName string `json:"user_name"`}

// GetUserInfoRequest 获取用户信息请求type GetUserInfoRequest struct { UserName string `json:"user_name"`}

// GetUserInfoResponse 获取用户信息返回结构type GetUserInfoResponse struct { UserName string `json:"user_name"` Age int `json:"age"` Gender string `json:"gender"` PassWord string `json:"pass_word"` NickName string `json:"nick_name"`}

// UpdateNickNameRequest 修改用户信息返回结构type UpdateNickNameRequest struct { UserName string `json:"user_name"` NewNickName string `json:"new_nick_name"`}

② user.goRegister函数 用户注册1234567891011121314151617181920212223242526272829303132333435func Register(req *RegisterRequest) error { if req.UserName == "" || req.Password == "" || req.Age


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3